#ifndef ____SSBASEL__SSBASE__BASE_DELEGATE__H__
#define ____SSBASEL__SSBASE__BASE_DELEGATE__H__
/*!
* \file  base_delegate.h
* \brief 
* 
*
* 
* \author patdz@qq.com
* \version 1.0
* \date 2014/06/21
*/
#include "base.h"
#include "base_stl.h"

_SSL_BEGIN
_SSBASEL_BEGIN

class SSBASE_CLASS delegate_base
{
public:
	delegate_base(void *obj, void *fn);
	delegate_base(const delegate_base &rhs);
	virtual ~delegate_base();

public:
	bool equal(const delegate_base &rhs) const;
	bool operator()(void *param);
	virtual delegate_base* copy() = 0;

protected:
	void* get_function();
	void* get_object();
	virtual bool invoke(void *param) = 0;

private:
	void *object_;
	void *function_;
};

typedef delegate_base* delegate_base_ptr;
typedef std::vector<delegate_base_ptr> delegate_base_ptrs;

class SSBASE_CLASS delegate_static : public delegate_base
{
	typedef bool (*func_ptr)(void*);
public:
	delegate_static(func_ptr pfn);
	delegate_static(const delegate_static &rhs);
	virtual delegate_base* copy();

protected:
	virtual bool invoke(void *param);
};

template<class O, class T>
class delegate : public delegate_base
{
	typedef bool (T::*func_ptr)(void*);
public:
	delegate(O *obj, func_ptr pfn) : delegate_base(obj, *(void**)(void*)&pfn),function_(pfn) { }
	delegate(const delegate &rhs) : delegate_base(rhs) { function_ = rhs.function_; }
	virtual delegate_base* copy() { return new delegate(*this); }

protected:
	virtual bool invoke(void *param)
	{
		O *obj = (O*)get_object();
		if(obj == NULL)
			return false;
		return (obj->*function_)(param);
	}
private:
	func_ptr function_;
};

template<class O, class T>
delegate<O,T> make_delegate(O *obj, bool (T::*fn)(void*))
{
	return delegate<O,T>(obj, fn);
}

inline delegate_static make_delegate(bool (*fn)(void*))
{
	return delegate_static(fn);
}

#pragma warning(push)
#pragma warning(disable:4251)
class SSBASE_CLASS event_source
{
	typedef bool (func_ptr)(void*);

public:
	event_source();
	~event_source();

	operator bool();
	void operator += (delegate_base &d);
	void operator += (func_ptr pfn);
	void operator -= (delegate_base &d);
	void operator -= (func_ptr pfn);
	bool operator()(void *param);

protected:
	delegate_base_ptrs delegates_;
};
#pragma warning(pop)

_SSBASEL_END
_SSL_END

#endif
